/*
 * Duplicate Detector Copyright (C) 2010 Marco Biscaro <marcobiscaro2112@gmail.com>
 * 
 * This file is part of Duplicate Detector.
 *
 * Duplicate Detector is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Duplicate Detector is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Duplicate Detector.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.googlecode.duplicatedetector.model;

import java.io.File;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import javax.swing.JTree;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;

/**
 * {@link TreeModel} used to show the results (all duplicated files in a tree
 * vision).
 * 
 * @author Marco Biscaro
 */
public class FileTreeModel extends AbstractTreeModel {

	public static final String HASH_PREFIX = "Hash MD5: ";
	private JTree tree;
	private Map<String, Set<File>> files;

	public FileTreeModel(JTree tree, Map<String, Set<File>> files) {
		this.tree = tree;
		this.files = files;
	}

	@Override
	public Object getChild(Object parent, int index) {
		if (parent == files) {
			int count = 0;
			for (String s : files.keySet()) {
				if (count++ == index) {
					return HASH_PREFIX + s;
				}
			}
			throw new IllegalArgumentException("Invalid index: " + index);
		}
		if (parent instanceof String) {
			int count = 0;
			for (File f : files.get(((String) parent).substring(HASH_PREFIX
					.length()))) {
				if (count++ == index) {
					return f;
				}
			}
			throw new IllegalArgumentException("Invalid index: " + index);
		}
		throw new IllegalArgumentException("Invalid parent class: "
				+ parent.getClass().getSimpleName());
	}

	@Override
	public int getChildCount(Object parent) {
		System.out.println(parent);
		if (parent == files) {
			return files.size();
		}
		if (parent instanceof String) {
			return files.get(((String) parent).substring(HASH_PREFIX.length()))
					.size();
		}
		if (parent instanceof File) {
			return 0;
		}
		throw new IllegalArgumentException("Invalid parent class: "
				+ parent.getClass().getSimpleName());
	}

	@Override
	public int getIndexOfChild(Object parent, Object child) {
		if (parent == files) {
			int count = 0;
			for (String s : files.keySet()) {
				if (s.equals(child)) {
					return count;
				}
				count++;
			}
		}
		if (parent instanceof String) {
			int count = 0;
			for (File f : files.get(((String) parent).substring(HASH_PREFIX
					.length()))) {
				if (f.equals(child)) {
					return count;
				}
				count++;
			}
		}
		return -1;
	}

	@Override
	public Object getRoot() {
		return files;
	}

	@Override
	public boolean isLeaf(Object node) {
		return node instanceof File;
	}

	public void remove(File f) {
		Iterator<Entry<String, Set<File>>> i = files.entrySet().iterator();
		int hash = 0;
		while (i.hasNext()) {
			Entry<String, Set<File>> entry = i.next();
			Set<File> set = entry.getValue();
			Iterator<File> i2 = set.iterator();
			int file = 0;
			while (i2.hasNext()) {
				File f2 = i2.next();
				if (f2.equals(f)) {
					i2.remove();
					TreePath p = tree.getSelectionPath();
					Object[] path = p.getPath();
					path = Arrays.copyOf(path, path.length - 1);
					fireTreeNodesRemoved(this, path, new int[] { file },
							new Object[] { f });
					// if there is one remaining file, remove the hash entry
					// FIXME
					if (set.size() < 2) {
						System.out.println("< 2");
						System.out.println(set);
						System.out.println(entry.getKey());
						System.out.println(hash);
						i.remove();
						fireTreeNodesRemoved(this, new Object[] { files },
								new int[] { hash }, new Object[] { HASH_PREFIX
										+ entry.getKey() });
					}
					break;
				}
				file++;
			}
			hash++;
		}
	}
}
